/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once


#include "intern/解算器/physics_解算器基类.h"
#include "S_Object.h"
//#define DEF_默认物理 E_物理引擎::E_物理引擎_NewTon
//#define DEF_默认物理 E_物理引擎::E_物理引擎_Chrono
//#define DEF_默认物理 E_物理引擎::E_物理引擎_PhysX
#define DEF_默认物理 E_物理引擎::E_物理引擎_PBF







EngineAPI_EXPORT S_物理解算器* f_创建物理解算器(uint32 id);
EngineAPI_EXPORT S_Physics* f_phy_创建创建解算器(E_物理引擎 type, vec3 域大小, S_设备环境* ctx = nullptr);

//EngineAPI_EXPORT S_PhyVehicle* f_phy_创建车辆(S_PhyVehicleParams& 车身
//										  , S_PhyWheel** 车轮, uint32 车轮数量
//										  , S_PxAxleParams& 车轴属性);
//physx::PxActor* f_phy_get_车身刚体(S_PhyVehicle* v);
//S_PhyWheel* f_phy_创建车轮(float32 半径, float32 宽度, float32 重量, float32 动量, float32 阻尼
//					   , physx::vehicle2::PxVehicleSuspensionParams* 悬挂属性
//					   , physx::vehicle2::PxVehicleSuspensionForceParams* 悬挂物理属性
//					   , physx::vehicle2::PxVehicleTireForceParams* 轮胎属性
//);
//void f_phy_添加模拟车辆(physx::PxScene* scene, S_PhyVehicle* 车辆);
//void f_phy_重置车辆模拟(physx::PxScene* scene);
//void f_phy_重置车辆模拟环境(physx::PxScene* scene);
//void f_phy_车辆模拟(physx::PxScene* scene, float32 dt);
//void f_phy_车辆操控状态(S_PhyVehicle* 车辆, S_VehicleCommand& command);
//void f_phy_车轮动力总成(S_PhyVehicle* 车辆, const S_VehiclePowertrain& 动力总成);


EngineAPI_EXPORT void f_销毁物理解算器(uint32 id);
EngineAPI_EXPORT void f_phy_销毁物理解算器(S_Physics* phy);
EngineAPI_EXPORT void f_phy_重构(S_Physics* phy, const std::string& path = "");
EngineAPI_EXPORT void f_phy_重置运动(S_Physics* phy);

EngineAPI_EXPORT void f_phy_构建缓存帧标记(S_Physics* phy, uint32 帧数量, const std::string& path);
EngineAPI_EXPORT bool f_phy_清除模拟帧标记(S_Physics* phy, int32 s, int32 e = -1, const std::string& path = "");
EngineAPI_EXPORT void f_phy_标记帧缓存(S_Physics* phy, int32 帧, int32 标记, const std::string& path);

EngineAPI_EXPORT void f_phy_步进解算(S_Physics* phy, float32 时间步进);
EngineAPI_EXPORT void f_phy_set飞溅粒子(S_Physics* phy, bool 是否开启, uint32 分配数量 = 0);
EngineAPI_EXPORT void f_phy_set模拟参数(S_Physics* phy, const S_PBF_Params& 模拟参数);

EngineAPI_EXPORT uint32 f_phy_get解算器域分辨率(S_Physics* phy);
EngineAPI_EXPORT uint32 f_物理解算器名词是否存在(uint32 key);

EngineAPI_EXPORT void f_Phy_构建静态网格碰撞划分(S_Physics* phy, float32 最小单元大小);


EngineAPI_EXPORT S_物理材质*		f_创建材质(S_物理解算器* 解算器, float32 静摩擦, float32 动摩擦, float32 恢复系数, E_物理引擎 物理引擎 = DEF_默认物理);

EngineAPI_EXPORT S_物理几何体*	f_phy_创建几何体(E_物理几何体类型 几何体类型, E_物理引擎 物理引擎 = DEF_默认物理);
EngineAPI_EXPORT void			f_phy_销毁几何体(S_物理几何体* body);
EngineAPI_EXPORT void			f_phy_创建几何体数据(S_物理几何体* geom, E_物理几何体类型 几何体类型);


EngineAPI_EXPORT S_物理几何体* f_创建平面几何体(S_物理解算器* 解算器, const vec4& v, E_物理引擎 物理引擎 = DEF_默认物理);
EngineAPI_EXPORT S_物理几何体* f_创建方体几何体(S_物理解算器* 解算器, const vec3& v, E_物理引擎 物理引擎 = DEF_默认物理);
EngineAPI_EXPORT S_物理几何体* f_创建球体几何体(S_物理解算器* 解算器, const float32 v, E_物理引擎 物理引擎 = DEF_默认物理);
EngineAPI_EXPORT S_物理几何体* f_创建凸壳物理包围几何(S_物理解算器* 解算器, const S_三角Mesh mesh, E_物理引擎 物理引擎 = DEF_默认物理);
EngineAPI_EXPORT S_物理几何体* f_创建网格物理几何体(S_物理解算器* 解算器, const S_三角Mesh mesh, E_物理引擎 物理引擎 = DEF_默认物理);
EngineAPI_EXPORT S_物理几何体* f_创建静态网格物理包围几何(S_物理解算器* 解算器, const S_三角Mesh mesh, E_物理引擎 物理引擎 = DEF_默认物理);

EngineAPI_EXPORT void f_phy_创建物理几何体(E_物理引擎 物理引擎, S_物理几何体* 几何体);
EngineAPI_EXPORT std::vector<S_物理体*> f_phy_get物理体(S_Physics* phy, E_物理几何体类型 几何类型);
EngineAPI_EXPORT void f_Phy_内部网格填充绑定物体(S_Physics* phy, std::vector<S_物理体*>& Body);

EngineAPI_EXPORT uint32	f_phy_get肌腱数量(S_Physics* phy);
EngineAPI_EXPORT void	f_phy_构建肌腱物体可视(S_Physics* phy, S_物体* Body);
EngineAPI_EXPORT void	f_phy_set肌腱力度(S_Physics* phy, float32* 力度, int32 id);
EngineAPI_EXPORT void	f_phy_施加力(S_Physics* phy, const S_施加物理力& f, E_施加力类型 type);

/*淘汰*/
EngineAPI_EXPORT S_物理体* f_创建物理平面(S_物理解算器* 解算器, S_物理几何体& geom, S_物理材质& mat, E_物理引擎 物理引擎 = DEF_默认物理);





EngineAPI_EXPORT S_物理体* f_创建静态碰撞(S_物理解算器* 解算器, S_物理几何体& geom, S_物理材质& mat, const S_Tranform& t);
EngineAPI_EXPORT S_物理体* f_创建刚体(S_物理解算器* 解算器, S_物理几何体& geom, S_物理材质& mat, const S_Tranform& t, float32 重量 = 1.0);
EngineAPI_EXPORT S_物理体* f_创建控制物理体(S_物理解算器* 解算器, S_物理几何体& geom, S_物理材质& mat, const S_Tranform& t);
EngineAPI_EXPORT S_物理体* f_创建物理边界(S_物理解算器* 解算器, vec3 size, const S_Tranform& t, E_物理引擎 物理引擎 = DEF_默认物理);
EngineAPI_EXPORT S_物理体* f_Phy_create刚体(S_Physics* phy, S_物理材质* 材质);
EngineAPI_EXPORT S_物理体* f_Phy_create刚体(S_Physics* phy, S_物理几何体& geom, S_物理材质* 材质);
EngineAPI_EXPORT S_物理体*	f_phy_create物理体(S_物理几何体* geom, S_物理材质* 材质, E_物理引擎 phy_type);
EngineAPI_EXPORT void		f_phy_销毁物理体(S_物理体* body);

EngineAPI_EXPORT S_物理体* f_Phy_create粒子发射(S_Physics* phy, uint32 粒子数, S_物理材质* 材质 = nullptr);


EngineAPI_EXPORT S_物理体* f_创建物理车轮(S_物理解算器* 解算器, S_物理几何体& geom, S_物理材质& mat, const S_车轮参数& 属性);
EngineAPI_EXPORT S_物理体* f_创建物理车辆(S_物理解算器* 解算器, S_车体参数& 车体参数 );

EngineAPI_EXPORT void	f_Phy_创建流体(S_Physics* phy, S_物理体* body);
//S_物理体* f_phy_create物理体(E_物理引擎 type);
EngineAPI_EXPORT void	f_Phy_销毁物理体(S_物理体* body);

EngineAPI_EXPORT void	f_车辆物理体绑定物体(S_物理解算器* 解算器, S_物理体* 车, std::vector<void*>& 车体);

/*void f_创建车(	S_物理解算器* 解算器, 
				S_物体* 车体, 
				const S_车体参数& 车体参数, 
				vector<S_物体*> 车轮, 
				const vector<S_车轮参数>& 车轮参数, 
				const S_三角Mesh& 车体mesh
);*/
EngineAPI_EXPORT void f_Phy_set肌腱力度(S_Physics* phy, float32* value, int32 num);
EngineAPI_EXPORT void f_Phy_应用力(S_Physics* 解算器, const S_施加物理力& 互交);


EngineAPI_EXPORT S_物理体*	f_create流体粒子(S_物理解算器* 解算器, S_物理材质& mat, const S_Tranform& t, uint32 num, E_物理引擎 物理引擎 = DEF_默认物理);
S_物理体*	f_create布料(S_物理解算器* 解算器, S_物理几何体& geom, S_物理材质& mat, const S_Tranform& t);
S_物理体*	f_create柔体(S_物理解算器* 解算器, S_物理几何体& geom, S_物理材质& mat, const S_Tranform& t);
EngineAPI_EXPORT S_物理体*	f_Phy_create流体(S_Physics* 解算器, S_物理几何体& geom, S_物理材质& mat, const S_Tranform& t, E_物理引擎 物理引擎);
//S_物理体*	f_Phy_create刚体(const S_Tranform& t, float32 重量 = 1.0);

EngineAPI_EXPORT bool		f_Phy_切换物理体类型(E_物理引擎 IdType, S_物理体* body, E_物理体类型 类型);
EngineAPI_EXPORT void		f_Phy_重置发射源(S_物理体* body);
EngineAPI_EXPORT S_体素*		f_Phy_get发射源体素(S_物理体* body);
EngineAPI_EXPORT S_域区*		f_Phy_get域属性(S_Physics* phy);
EngineAPI_EXPORT uint64		f_Phy_get粒子数量(S_Physics* phy);
EngineAPI_EXPORT float32		f_Phy_get粒子大小(S_Physics* phy);

EngineAPI_EXPORT void		f_Phy_get域中粒子(S_Physics* phy, const vec3& coord, std::vector<vec3>& particle);
EngineAPI_EXPORT uvec2		f_Phy_get粒子区间(S_物理体* body);
EngineAPI_EXPORT uvec4		f_Phy_get粒子发射区间(S_物理体* body, float32 速率);
EngineAPI_EXPORT uint64		f_Phy_get发射总数(S_物理体* body);
EngineAPI_EXPORT void		f_phy_发射粒子(S_Physics* phy, S_物理体* body, const S_Vec3Array* point, const S_Vec3Array* vel);


EngineAPI_EXPORT void		f_phy_initPBF模拟参数(S_PBF_Params& params);

EngineAPI_EXPORT S_物理体*	f_phy_get物理体(S_Physics* phy, std::u16string& bodyName);


EngineAPI_EXPORT void f_phy_添加物理体(S_物理解算器* 解算器, S_物理体* body, uint32 sceneKey, E_物理引擎 物理引擎 = DEF_默认物理);
EngineAPI_EXPORT void f_物理体从引擎移除(S_物理解算器* 解算器, S_物理体* body, uint32 sceneKey, E_物理引擎 物理引擎 = DEF_默认物理);
EngineAPI_EXPORT bool f_Phy_物理体添加到引擎(S_Physics* phy, S_物理体* body);
EngineAPI_EXPORT void f_phy_添加物理体(S_Physics* phy, S_PhyBodyArray* body);

EngineAPI_EXPORT void	f_Phy_add静态碰撞网格(S_Physics* phy, std::vector<vec3>& vert, std::vector<uvec3>& index);

EngineAPI_EXPORT void f_物理体添加碰撞回调(S_物理解算器* 解算器, S_物理体* body, uint32 sceneKey, E_物理引擎 物理引擎 = DEF_默认物理);

EngineAPI_EXPORT 车辆容器_t f_get车辆(S_物理解算器* 解算器, E_物理引擎 物理引擎 = DEF_默认物理);

EngineAPI_EXPORT void f_施加力(S_物理解算器* 解算器, S_物理体* body, const vec3& 力, E_物理引擎 物理引擎 = DEF_默认物理);


EngineAPI_EXPORT void	f_Phy_设置粒子数量(S_物理解算器* 解算器, S_物理体* body, uint32 num, E_物理引擎 物理引擎 = DEF_默认物理);
EngineAPI_EXPORT void	f_Phy_拷贝粒子坐标(S_物理解算器* 解算器, S_物理体* body, vec3* c, E_物理引擎 物理引擎 = DEF_默认物理);
EngineAPI_EXPORT void	f_Phy_拷贝粒子速度(S_物理解算器* 解算器, S_物理体* body, vec3* c, E_物理引擎 物理引擎 = DEF_默认物理);

EngineAPI_EXPORT vec3*	f_Phy_映射粒子坐标(S_物理解算器* 解算器, S_物理体* body, E_物理引擎 物理引擎 = DEF_默认物理);
EngineAPI_EXPORT vec3*	f_Phy_映射粒子速度(S_物理解算器* 解算器, S_物理体* body, E_物理引擎 物理引擎 = DEF_默认物理);
EngineAPI_EXPORT vec3*	f_Phy_映射粒子外力(S_物理解算器* 解算器, S_物理体* body, E_物理引擎 物理引擎 = DEF_默认物理);




EngineAPI_EXPORT void	f_Phy_set解算器域分辨率(S_Physics* phy, E_物理引擎 type, uint32 分辨率, vec3 世界大小, float32 单元间隔);
EngineAPI_EXPORT void	f_Phy_set解算器域分辨率(S_Physics* phy, float32 分辨率);
EngineAPI_EXPORT void	f_phy_set解算器域(S_Physics* phy, const vec3& 域大小, const vec3& 域偏移, float32 单元大小);
//EngineAPI_EXPORT void	f_Phy_set流体密度(S_Physics* phy, S_物理体* body);
//EngineAPI_EXPORT void	f_Phy_set流体速度(S_Physics* phy, S_物理体* body);
EngineAPI_EXPORT void	f_Phy_set粒子发射(S_物理体* e, std::vector<S_VN>& vn);
EngineAPI_EXPORT void	f_Phy_set粒子发射最大数量(S_物理体* e, uint64 num);
EngineAPI_EXPORT void	f_Phy_set流体飞溅粒子数量(S_Physics* phy, uint32 num);
EngineAPI_EXPORT void	f_Phy_set粒子区间(S_物理体* body, const uvec2& 区间, uint64 全局偏移);
EngineAPI_EXPORT void	f_Phy_添加物理体(S_Physics* phy, std::vector<S_物理体*>& body);

EngineAPI_EXPORT void	f_phy_添加力(S_Physics* phy, const std::vector<S_PBF_force>& 力);

EngineAPI_EXPORT void	f_phy_更新粒子绘制缓存(S_Physics* phy, float32 子帧步进);

EngineAPI_EXPORT void	f_Phy_取流体调试数据(S_Physics* phy, void* data);
EngineAPI_EXPORT void	f_Phy_取流体调试数据(S_Physics* phy, S_物体* ob, uint32 信息类型 = 0);
EngineAPI_EXPORT void	f_Phy_取体素调试数据(S_Physics* phy, std::vector<vec4>& data);
EngineAPI_EXPORT void	f_Phy_get静态碰撞空间树调试数据(const S_Physics* phy, std::vector<vec4>& data, bool 不包含空单元 = true);


EngineAPI_EXPORT bool	f_phy_读取缓存(S_Physics* phy, const std::string path[2], E_物理缓存方式 缓存方式, int32 帧);
EngineAPI_EXPORT void	f_phy_写入缓存(S_Physics* phy, const std::string& path, E_物理缓存方式 缓存方式);

EngineAPI_EXPORT void	f_phy_模拟(S_Physics* phy, int32 帧);


